`define VERSION 32'h00000014

module mydebugger (
    input           clk,
    input           clk_50M,
    input           reset_n,

    //external
    output reg cy_rst_out,
    inout [15:0] cyData,
    input cy_IFCLK                     ,
    input cy_to_fpga_CTL0_FLAGA        ,//EP2EMPTY
    //input cy_to_fpga_CTL2_FLAGC        ,// 可以省略
    input cy_to_fpga_CTL1_FLAGB        ,//EP6FULL
    //input cy_to_fpga_A7_FLAGD          ,// 可以省略
    output cy_from_fpga_RDY1_SLWR       ,//output
    output cy_from_fpga_RDY0_SLRD       ,//output
    output cy_from_fpga_A2_SLOE         ,//output
    input cy_A0_INT0                   ,// in from pc
    output reg cy_A1_INT1                   ,// out to pc
    input cy_A3_WU2                    ,//cmd clk
    output cy_from_fpga_A5_FIFOADR1     ,//output 可以省略 同 cy_from_fpga_A2_SLOE

    //cpu
    output reg          debug_reset_n,
    output reg          halt_debug,
    output reg          debug_step,
    input               halt_cpu,
    //input        [31:0] curr_data,
    //input        [31:0] pcResult,
    //input        [31:0] private_offset,
    //input        [31:0] private_offset_rear,
    input        [31:0] pc,
    input        [31:0] cpu_address,
    input               irq_enable,
    //input        [31:0] irq_addr,

    output reg          debug_rw_req,
    output reg          debug_rw,
    output              debug_read_ins,
    output              debug_ins_hold_value,
    output reg  [31:0]  debug_address_data,
    output reg  [31:0]  debug_address_ins,
    output reg  [31:0]  debug_writedata_data,

    input       [31:0]  avm_m0_address,
    input               avm_m0_request,
    input               avm_m0_rw,
    input       [31:0]  avm_m0_readdata,
    input               avm_m0_waitrequest,
    input               avm_m1_read,
    input       [31:0]  avm_m1_readdata,
    input               avm_m1_waitrequest,
    input               irq_req,
    input         [4:0] irq_id,

    output reg          debug_regReq,
    input               debug_regAck,
    output reg          debug_regIsWrite,
    output       [8:0]  debug_regAddr,//2k/4 = 512*32bit
    output reg  [31:0]  debug_regWriteData,
    input       [31:0]  debug_regData,

    output        [7:0] pc_record_index_read,
    input        [35:0] pc_record_data,
    input        [31:0] pc_record_index,
    
    output        [7:0] debug_stash_index_read,
    input        [31:0] debug_stash_data,
    input         [7:0] debug_stash_index,

    //spirom
    output reg        spirom_debug_read_req     ,
    input             spirom_debug_read_ack     ,
    input       [7:0] spirom_debug_read_data    ,
    output reg        spirom_debug_write_req    ,
    input             spirom_debug_write_ack    ,
    output reg  [7:0] spirom_debug_write_data   ,
    output reg        spirom_debug_cs           ,

    //vga
    output            vga_control_by_debugger,
    input             vga_control_by_debugger_accepted,
    output reg        vga_debugger_read_line_req,
    output      [9:0] vga_debugger_read_line_burst,
    input             vga_debugger_read_line_ack,
    output     [18:0] vga_debugger_read_line_addr,//1Gbyte range 2k byte/line
    output      [1:0] vga_debugger_read_line_part,
    
    output      [9:0] vga_debugger_read_pixel_addr,
    output            vga_debugger_read_pixel_clk,
    input      [15:0] vga_debugger_read_pixel_data,
    input      [31:0] vga_debugger_read_pixel_data32,


    output reg        debug_nocache,
    output reg [31:0] debug_hid,
    output reg        debug_hid_req,

    //misc
    output reg        debug_flg,
    input      [31:0] debug_tx_to_pc,
    input             debug_tx_to_pc_valid,
    output reg        debug_tx_to_pc_read,
    output reg [31:0] debug_rx_from_pc,
    output reg        debug_rx_from_pc_valid,
    input             debug_rx_from_pc_read,
    output reg [31:0] debug_vga_base_addr,
    input      [31:0] memSize,
    input      [31:0] vga_base_addr,
    output reg        cpu_clk_sel,

    input dummy
);


//----------------------------------------------------lowspeed start-----------------------------------------------------------
reg command_req;
reg command_ack;
reg debug_data_send;
reg [31:0] debug_data_out;
wire [31:0] data;
wire [7:0] command;
assign debug_regAddr = debug_address[5:0];

reg [20:0] cy_rst_out_cnt;
always @(posedge clk_50M or negedge reset_n) begin
  if (!reset_n) begin
    cy_rst_out <= 0;
    cy_rst_out_cnt <= 0;
  end else begin
    if(!cy_rst_out_cnt[20])begin
      cy_rst_out <= 0;
      cy_rst_out_cnt <= cy_rst_out_cnt+1'b1;
    end else begin
      cy_rst_out <= 1;
    end
  end
end

reg cy_snd_req_buff;
assign command = rec_data[7:0];
assign data = rec_data[39:8];
reg [4:0]cy_snd_cnt;

reg [5:0] cmd_status;
reg [39:0] rec_data;//[0]:end flg [41:9]:data [8:1] cmd
reg [31:0] snd_data_buff;
reg command_ack_buff;
reg cy_snd_ack;
reg command_req_trans;
always @(posedge cy_A3_WU2 or negedge reset_n) begin
  if (!reset_n) begin
    command_req_trans<=0;
    cy_snd_ack<=0;
    cy_A1_INT1<=0;
    
    rec_data <= 0;
    cmd_status<=0;
    snd_data_buff<=0;
    command_ack_buff<=0;
    cy_snd_req_buff<=0;
  end else begin
    command_ack_buff<=command_ack;
    cy_snd_req_buff<=cy_snd_req;
    
    if(cmd_status==0)begin
      if(cy_A0_INT0)begin
        cmd_status <= 1;
        rec_data<=40'b0;
      end
    end else begin
      cmd_status<=cmd_status+1'b1;
      rec_data <={cy_A0_INT0,rec_data[39:1]};
      if(cmd_status==40)begin
        cmd_status<=0;
        command_req_trans<=1;
      end
    end
    
    if(command_ack_buff)begin
      command_req_trans<=0;
    end

    if(cy_snd_req_buff && !cy_snd_ack)begin
      if(cmd_status==0)begin
        cmd_status<=1;
        cy_A1_INT1<=1;
        snd_data_buff<=debug_data_out;
      end else begin
        cmd_status<=cmd_status+1'b1;
        cy_A1_INT1<=snd_data_buff[0];
        snd_data_buff<={1'b0,snd_data_buff[31:1]};
        if(cmd_status==33)begin
          cy_A1_INT1<=0;
          cmd_status<=0;
          cy_snd_ack<=1;
        end
      end
    end
    
    if(!cy_snd_req_buff && cy_snd_ack)begin
      cy_snd_ack<=0;
    end

  end
end

reg cy_snd_req;
reg cy_snd_ack_buff;
reg command_req_trans_buff;
always @(posedge clk_50M or negedge reset_n) begin
  if (!reset_n) begin
    command_req<=0;
    cy_snd_req<=0;
    cy_snd_ack_buff<=0;
  end else begin
    cy_snd_ack_buff<=cy_snd_ack;
    
    command_req <= command_req_trans;
    
    if(debug_data_send)begin
      cy_snd_req <= 1;
    end
    
    if(cy_snd_ack_buff)begin
      cy_snd_req <= 0;
    end
  end
end

//----------------------------------------------------lowspeed end-------------------------------------------------------------



//----------------------------------------------------hispeed start------------------------------------------------------------
localparam FIFO_SIZE = 7;
reg transfer_req;
reg transfer_req_buff;
reg sync_req_buff;
reg sync_ack;
reg sync_req;
reg sync_ack_buff;
reg  [FIFO_SIZE:0] ft_addr;
wire [FIFO_SIZE:0] ft_addr_next = ft_addr + 1'b1;
reg  [FIFO_SIZE:0] ft_addr_temp;
reg  [FIFO_SIZE:0] ft_addr_buff;
reg  [FIFO_SIZE:0] fpga_addr;
wire [FIFO_SIZE:0] fpga_addr_next = fpga_addr + 1'b1;
reg  [FIFO_SIZE:0] fpga_addr_temp;
reg  [FIFO_SIZE:0] fpga_addr_buff;
reg [31:0] ft_read_data_buff;
reg         ft_write; 
reg  [31:0] ft_write_data;
wire [31:0] ft_read_data;
reg         fpga_write;
reg  [31:0] fpga_write_data;
wire [31:0] fpga_read_data;
reg RD;
reg WR;
reg ft_out_to_pc_buff;
reg reset_fifo_buff;

reg  [1:0] ft_status;

assign cyData = ft_out_to_pc ? cyData_out : 16'hzzzz;
//cy_from_fpga_A6_PKTEND<=1;
//cy_from_fpga_A4_FIFOADR0 <= 0;
//assign cy_from_fpga_A5_FIFOADR1 = transfer_type==1 ? 1'b0 : 1'b1;//0:fpga to pc     1:pc to fpga
assign cy_from_fpga_A5_FIFOADR1 = ft_out_to_pc ? 1'b1 : 1'b0;
assign cy_from_fpga_A2_SLOE = ft_out_to_pc ? 1'b1 : 1'b0;

wire ft_out_to_pc = (mem_cmd==MEM_READ_TRANS) || (mem_cmd==INS_READ_TRANS) || (mem_cmd==VGA_TRANS);
wire [15:0] cyData_out = ft_read_data_buff[15:0];

assign cy_from_fpga_RDY0_SLRD = ~RD;
assign cy_from_fpga_RDY1_SLWR = ~WR;
wire EP2EMPTY = ~cy_to_fpga_CTL0_FLAGA;//pc 2 fpga
//wire EP2FULL  = !cy_to_fpga_CTL1_FLAGB;
//wire EP6EMPTY = !cy_to_fpga_CTL2_FLAGC;
//wire EP6FULL  = ~cy_to_fpga_A7_FLAGD;//fpga 2 pc

wire EP6FULL  = ~cy_to_fpga_CTL1_FLAGB;//fpga 2 pc

always @(posedge cy_IFCLK or negedge reset_n) begin
  if (!reset_n) begin
    ft_status <= 0;
    ft_write <= 0;
    ft_write_data <= 0;
    RD<=0;
    WR<=0;
    ft_addr <= 0;
    ft_addr_temp <= 0;
    fpga_addr_buff <= 0;
    sync_req_buff <= 0;
    sync_ack <= 0;
    transfer_req_buff <= 0;
    ft_out_to_pc_buff <= 0;
    reset_fifo_buff <= 0;

  end else begin
    sync_req_buff <= sync_req;
    ft_write <= 0;
    RD<=0;
    WR<=0;
    ft_out_to_pc_buff <= ft_out_to_pc;
    reset_fifo_buff <= reset_fifo;

    if(sync_req_buff && !sync_ack)begin
        sync_ack <= 1;
        ft_addr_temp <= ft_addr;
    end
    if(!sync_req_buff && sync_ack)begin
        sync_ack <= 0;
        fpga_addr_buff <= fpga_addr_temp;
    end

    transfer_req_buff <= transfer_req;

    if(transfer_req_buff)begin
      if(ft_out_to_pc_buff)begin
        case(ft_status)
        0: begin
          if(ft_addr != fpga_addr_buff)begin//ft_addr读取  fpga_addr_buff写入
            ft_status <= 1;
            ft_read_data_buff <= ft_read_data;
          end
        end
        1: begin
          if(!EP6FULL)begin
            WR <= 1;
            ft_status <= 2;
          end
        end
        2: begin
          ft_status <= 3;
          ft_read_data_buff <= {16'b0, ft_read_data_buff[31:16]};
          ft_addr <= ft_addr + 1'b1;
        end
        3: begin
          if(!EP6FULL)begin
            WR <= 1;
            ft_status <= 0;
          end
        end
        endcase
      end else begin
        case(ft_status)
        // pc->fpga 
        0: begin //接收
          if(!EP2EMPTY)begin
            ft_status <= 1;
            RD <= 1;
            ft_write_data <= {cyData, ft_write_data[31:16]};
          end
        end
        1: begin
          if(ft_addr_next != fpga_addr_buff)begin//ft_addr写入  fpga_addr_buff读取
            ft_status <= 2;
          end
        end
        2: begin //接收
          if(!EP2EMPTY)begin
            RD <= 1;
            ft_write_data <= {cyData, ft_write_data[31:16]};
            ft_write <= 1;
            ft_status <= 3;
          end
        end
        3: begin
          ft_addr <= ft_addr + 1'b1;
          ft_status <= 0;
        end
        endcase
      end
    end

    

    if(reset_fifo_buff)begin
      ft_status <= 0;
      ft_addr <= 0;
    end

  end
end

commonRamTDP #(
  .WORD_WIDTH(32),
  .ADDR_WIDTH(9),
  .BYTE_SIZE(8),
  .BE_WIDTH(4)
)fifoBuff(
  .clka(cy_IFCLK),
  .addra(ft_addr),
  .wea(ft_write),
  .bea(4'b1111),
  .dina(ft_write_data),
  .douta(ft_read_data),
  
  .clkb(clk),
  .addrb(fpga_addr),
  .web(fpga_write),
  .beb(4'b1111),
  .dinb(fpga_write_data),
  .doutb(fpga_read_data)
);

//----------------------------------------------------hispeed end--------------------------------------------------------------



//----------------------------------------------------mem start----------------------------------------------------------------
localparam MEM_READ             = 0;
localparam MEM_WRITE            = 1;
localparam INS_READ             = 2;
localparam REG_READ             = 3;
localparam MEM_READ_TRANS       = 4;
localparam MEM_WRITE_TRANS      = 5;
localparam INS_READ_TRANS       = 6;
localparam VGA_TRANS            = 7;

localparam MEM_IDLE             = 0;
localparam MEM_STEP1            = 1;
localparam MEM_2                = 2;
localparam MEM_3                = 3;
localparam MEM_4                = 4;
localparam MEM_5                = 5;
localparam MEM_WRITE_TRANS_PRE  = 6;
localparam MEM_7                = 7;

reg debug_read_ins_reg;
wire avm_m1_waitrequest_mid;

`ifdef DEBUG_INS_BUS
  assign debug_read_ins = debug_read_ins_reg;
  assign avm_m1_waitrequest_mid = avm_m1_waitrequest;
`else
  assign debug_read_ins = 0;
  assign avm_m1_waitrequest_mid = 0;
`endif
  

  assign vga_debugger_read_pixel_clk = clk;

  assign debug_ins_hold_value = 0;
  reg mem_req;
  reg [2:0] mem_cmd;  // 0 MEM_READ       1 MEM_WRITE       2 INS_READ       3 REG_READ
                      // 4 MEM_READ_TRANS 5 MEM_WRITE_TRANS 6 INS_READ_TRANS 7 VGA_TRANS
  reg mem_req_buff;
  reg mem_ack;
  reg [2:0] mem_status;
  reg [31:0] avm_readdata_latch;
  reg vga_debugger_read_line_ack_buff;

  wire [31:0] debug_address_end = debug_address + debug_length;

  assign vga_debugger_read_line_part[0] = 0;

  assign {vga_debugger_read_line_addr, vga_debugger_read_line_part[1]} = vga_debugger_read_line_addr_combine;
  reg [19:0] vga_debugger_read_line_addr_combine;
  
  assign vga_control_by_debugger = vga_control_by_debugger_reg || vga_control_by_debugger_reg2;

  assign vga_debugger_read_pixel_addr = {vga_debugger_read_line_part[1], vga_debugger_read_pixel_cnt};
  reg [8:0] vga_debugger_read_pixel_cnt;
  reg vga_control_by_debugger_accepted_buff;
  reg reset_fifo_buff_fpga;
  reg vga_control_by_debugger_reg;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      sync_req <= 0;
      sync_ack_buff <= 0;
      ft_addr_buff <= 0;
      fpga_addr_temp <= 0;
      fpga_addr <= 0;

      mem_ack <= 0;
      mem_req_buff <= 0;
      debug_rw_req <= 0;
      debug_read_ins_reg <= 0;
      debug_address_data <= 0;
      debug_address_ins <= 0;
      debug_rw <= 0;
      debug_writedata_data <= 0;


      vga_debugger_read_line_req <= 0;
      vga_debugger_read_line_addr_combine <= 0;
      vga_debugger_read_line_ack_buff <= 0;
      vga_control_by_debugger_reg <= 0;
      fpga_write <= 0;
      fpga_write_data <= 0;

      vga_debugger_read_pixel_cnt <= 0;
      vga_control_by_debugger_accepted_buff <= 0;
      reset_fifo_buff_fpga <= 0;
    end else begin
      sync_ack_buff <= sync_ack;
      mem_req_buff <= mem_req;
      debug_rw_req <= 0;
      debug_read_ins_reg <= 0;
      fpga_write <= 0;
      vga_debugger_read_line_ack_buff <= vga_debugger_read_line_ack;
      vga_control_by_debugger_accepted_buff <= vga_control_by_debugger_accepted;
      reset_fifo_buff_fpga <= reset_fifo;

      if(!sync_ack_buff && !sync_req)begin
          sync_req <= 1;
          fpga_addr_temp <= fpga_addr;
      end
      if(sync_ack_buff && sync_req)begin
          sync_req <= 0;
          ft_addr_buff <= ft_addr_temp;
      end
    
      fpga_write_data <= 0;
      case(mem_cmd)
      MEM_READ:begin
      end
      MEM_WRITE:begin
      end
      INS_READ:begin
      end
      REG_READ:begin
      end
      MEM_READ_TRANS:begin
        fpga_write_data <= avm_readdata_latch;
      end
      MEM_WRITE_TRANS:begin
      end
      INS_READ_TRANS:begin
        fpga_write_data <= avm_readdata_latch;
      end
      VGA_TRANS:begin
        fpga_write_data <= vga_debugger_read_pixel_data32;//{vga_debugger_read_pixel_data, avm_readdata_latch[15:0]};
      end
      endcase

      case(mem_status)
      MEM_IDLE: begin
        fpga_addr <= 0;
        vga_debugger_read_line_req <= 0;
        debug_address_data <= {debug_address[31:2],2'b0};
        debug_address_ins <= {debug_address[31:2],2'b0};
        vga_debugger_read_line_addr_combine <= debug_address[29:10];//sdram_rw_addr <= {read_line_addr[14:0],2'b(read_line_part),9'b0};//14bit is 2k * 16k 32M,  15bit is 64M
        vga_control_by_debugger_reg <= 0;
        if(mem_req_buff && !mem_ack)begin
          mem_status <= MEM_STEP1;
          if(mem_cmd==VGA_TRANS)begin
            vga_control_by_debugger_reg <= 1;
          end
        end
      end
      MEM_STEP1: begin
        debug_writedata_data <= debug_writedata;
        case(mem_cmd)
        MEM_READ:begin
          debug_rw <= 0;// sendCmd(SET_DEBUG_RW_CMD, 0);//ldw
          debug_rw_req <= 1;
          mem_status <= MEM_2;
        end
        MEM_WRITE:begin
          debug_rw <= 1;//     case 0: debug_rw_cmd = 1; break;//3'b001;//stw
          debug_rw_req <= 1;
          //debug_writedata_data <= debug_writedata;
          mem_status <= MEM_2;
        end
        INS_READ:begin
          debug_read_ins_reg <= 1;
          mem_status <= MEM_2;
        end
        REG_READ:begin
          mem_status <= MEM_2;
        end
        MEM_READ_TRANS:begin
          debug_rw <= 0;// sendCmd(SET_DEBUG_RW_CMD, 0);//ldw
          debug_rw_req <= 1;
          mem_status <= MEM_2;
        end
        MEM_WRITE_TRANS:begin
          if(fpga_addr != ft_addr_buff)begin
            mem_status <= MEM_WRITE_TRANS_PRE;
          end
        end
        INS_READ_TRANS:begin
          debug_read_ins_reg <= 1;
          mem_status <= MEM_2;
        end
        VGA_TRANS:begin
          if(vga_control_by_debugger_accepted_buff)begin
            mem_status <= MEM_2;
          end
        end
        endcase
      end
      

      MEM_WRITE_TRANS_PRE: begin
        mem_status <= MEM_2;
        debug_rw <= 1;//     case 0: debug_rw_cmd = 1; break;//3'b001;//stw
        debug_rw_req <= 1;
        debug_writedata_data <= fpga_read_data;
        fpga_addr <= fpga_addr + 1'b1;
      end

      MEM_2: begin
        mem_status <= MEM_3;
        case(mem_cmd)
        MEM_READ:begin
        end
        MEM_WRITE:begin
        end
        INS_READ:begin
        end
        REG_READ:begin
        end
        MEM_READ_TRANS:begin
        end
        MEM_WRITE_TRANS:begin
        end
        INS_READ_TRANS:begin
        end
        VGA_TRANS:begin
          if(vga_debugger_read_line_addr_combine==debug_address_end[29:10])begin
            mem_status <= MEM_IDLE;
            mem_ack <= 1;
          end else begin
            mem_status <= MEM_3;
            vga_debugger_read_line_req <= 1;
            vga_debugger_read_pixel_cnt <= 0;
          end
        end
        endcase
      end
      MEM_3: begin
        case(mem_cmd)
        MEM_READ:begin
          avm_readdata_latch <= avm_m0_readdata;
          if(!avm_m0_waitrequest)begin
            mem_status <= MEM_IDLE;
            mem_ack <= 1;
          end
        end
        MEM_WRITE:begin
          if(!avm_m0_waitrequest)begin
            mem_status <= MEM_IDLE;
            mem_ack <= 1;
          end
        end
        INS_READ:begin
          avm_readdata_latch <= avm_m1_readdata;
          if(!avm_m1_waitrequest_mid)begin
            mem_status <= MEM_IDLE;
            mem_ack <= 1;
          end
        end
        REG_READ:begin
          avm_readdata_latch <= debug_regData;
          mem_status <= MEM_IDLE;
          mem_ack <= 1;
        end
        MEM_READ_TRANS:begin
          avm_readdata_latch <= avm_m0_readdata;
          if(!avm_m0_waitrequest)begin
            mem_status <= MEM_4;
          end
        end
        MEM_WRITE_TRANS:begin
          if(!avm_m0_waitrequest)begin
            mem_status <= MEM_4;
          end
        end
        INS_READ_TRANS:begin
          avm_readdata_latch <= avm_m1_readdata;
          if(!avm_m1_waitrequest_mid)begin
            mem_status <= MEM_4;
          end
        end
        VGA_TRANS:begin
          if(vga_debugger_read_line_ack_buff)begin
            vga_debugger_read_line_req <= 0;
            mem_status <= MEM_4;
          end
        end
        endcase

      end
      MEM_4: begin
        case(mem_cmd)
        MEM_READ:begin
        end
        MEM_WRITE:begin
        end
        INS_READ:begin
        end
        REG_READ:begin
        end
        MEM_READ_TRANS:begin
          //fpga_write_data <= avm_readdata_latch;
          if(ft_addr_buff != fpga_addr_next)begin
            fpga_write <= 1;
            debug_address_data <= debug_address_data + 4;
            mem_status <= MEM_5;
          end
        end
        MEM_WRITE_TRANS:begin
            debug_address_data <= debug_address_data + 4;
            mem_status <= MEM_5;
        end
        INS_READ_TRANS:begin
          //fpga_write_data <= avm_readdata_latch;
          if(ft_addr_buff != fpga_addr_next)begin
            fpga_write <= 1;
            debug_address_ins <= debug_address_ins + 4;
            mem_status <= MEM_5;
          end
        end
        VGA_TRANS:begin
          //fpga_write_data <= vga_debugger_read_pixel_data32;
          if(ft_addr_buff != fpga_addr_next)begin
            fpga_write <= 1;
            mem_status <= MEM_5;
          end
        end
        endcase
      end
      MEM_5: begin
        case(mem_cmd)
        MEM_READ:begin
        end
        MEM_WRITE:begin
        end
        INS_READ:begin
        end
        REG_READ:begin
        end
        MEM_READ_TRANS:begin
          fpga_addr <= fpga_addr + 1'b1;
          if(debug_address_data == {debug_address_end[31:2],2'b0})begin
            mem_status <= MEM_IDLE;
            mem_ack <= 1;
          end else begin
            mem_status <= MEM_STEP1;
          end
        end
        MEM_WRITE_TRANS:begin
          if(debug_address_data == {debug_address_end[31:2],2'b0})begin
            mem_status <= MEM_IDLE;
            mem_ack <= 1;
          end else begin
            mem_status <= MEM_STEP1;
          end
        end
        INS_READ_TRANS:begin
          fpga_addr <= fpga_addr + 1'b1;
          if(debug_address_ins == {debug_address_end[31:2],2'b0})begin
            mem_status <= MEM_IDLE;
            mem_ack <= 1;
          end else begin
            mem_status <= MEM_STEP1;
          end
        end
        VGA_TRANS:begin
          vga_debugger_read_pixel_cnt <= vga_debugger_read_pixel_cnt + 2;
          mem_status <= MEM_7;
        end
        endcase

      end

      MEM_7: begin
        fpga_addr <= fpga_addr + 1'b1;
        if(vga_debugger_read_pixel_cnt == 0)begin
          vga_debugger_read_line_addr_combine <= vga_debugger_read_line_addr_combine + 1'b1;
          mem_status <= MEM_2;
        end else begin
          mem_status <= MEM_4;
        end

      end

      endcase
      
      if(!mem_req_buff && mem_ack)begin
        mem_ack <= 0;
      end
      
      if(reset_fifo_buff_fpga)begin
        fpga_addr <= 0;
        mem_status <= MEM_IDLE;
        mem_ack <= 0;
        vga_debugger_read_line_req <= 0;
      end
    end
  end

//----------------------------------------------------mem end------------------------------------------------------------------



//----------------------------------------------------cmd start----------------------------------------------------------------
assign vga_debugger_read_line_burst = 511;//字
assign pc_record_index_read = debug_address[7:0];
assign debug_stash_index_read = debug_address[7:0];


reg [23:0] accessTime;
reg        accessTimeCnt;
reg        accessTimeCntLast;
always @(posedge clk or negedge reset_n) begin
  if (!reset_n) begin
    accessTime <= 0;
    accessTimeCnt <= 0;
    accessTimeCntLast <= 0;
  end else begin
    accessTimeCntLast <= accessTimeCnt;
    if(avm_m0_request || avm_m1_read)begin
      accessTimeCnt <= 1;
    end else begin
      accessTimeCnt <= 0;
    end
    if(accessTimeCnt)begin
      if(!accessTimeCntLast)begin
        accessTime <= 0;
      end else begin
        accessTime <= accessTime + 1'b1;
      end
    end
  end
end

always @(*)begin
  case(command[6:0])
`ifndef BASIC
    8'h01: begin debug_data_out<={24'h123456,4'b00,EP2EMPTY,1'b0,1'b1,EP6FULL}; end
`else
    8'h01: begin debug_data_out<={24'h123456,4'b01,EP2EMPTY,1'b0,1'b1,EP6FULL}; end
`endif

    8'h1D: begin debug_data_out<=debug_regData; end //GET_CONST_ECHO

    8'h20: begin debug_data_out<=data; end //GET_CONST_ECHO
    8'h21: begin debug_data_out<=pc_record_data[35:32]; end //GET_PC_RECORD_DATA_EXT
    8'h22: begin debug_data_out<=accessTime; end //GET_ACCESS_TIME
    8'h23: begin debug_data_out<=avm_m0_address; end //GET_AVM_M0_ADDRESS
    8'h24: begin debug_data_out<=`VERSION; end //GET_CONST_ECHO
    8'h25: begin debug_data_out<=pc_record_data[31:0]; end //GET_PC_RECORD_DATA
    8'h26: begin debug_data_out<=pc_record_index; end //GET_PC_RECORD_INDEX
    8'h27: begin debug_data_out<={avm_m1_waitrequest,halt_cpu,halt_debug,avm_m0_waitrequest,irq_enable,irq_req}; end //GET_MISC
    8'h28: begin debug_data_out<=irq_id; end //GET_IRQ_ID
    8'h29: begin debug_data_out<=cpu_address; end //GET_CPU_ADDRESS
    8'h2A: begin debug_data_out<=pc; end // GET_PC
    8'h2B: begin debug_data_out<=memSize; end // GET_MEM_SIZE
    8'h2C: begin debug_data_out<=vga_base_addr; end // GET_VGA_BASE_ADDR
    8'h2D: begin debug_data_out<=mem_cmd; end // GET_VGA_BASE_ADDR
    
    8'h2E: begin debug_data_out<=debug_stash_data; end //  GET_DEBUG_STASH_DATA
    8'h2F: begin debug_data_out<=debug_stash_index; end // GET_DEBUG_STASH_INDEX


    8'h30,8'h31,8'h32,8'h33,
    8'h34,8'h35,8'h36,8'h37 : begin//MEM_READ
      debug_data_out <= avm_readdata_latch; 
    end


    8'h72 : begin debug_data_out<=spirom_debug_read_data; end
    8'h73 : begin debug_data_out<=123; end
    8'h74 : begin debug_data_out<=123; end
    
    //spirom 批量
            //内存批量 len = data start = debug_address
    8'h76 : begin debug_data_out<=123; end


    default: begin
      debug_data_out<=0;
    end
  endcase
end
  reg [1:0] reg_state;
  reg debug_regAck_buff;
  reg vga_control_by_debugger_reg2;
  reg [31:0] debug_address;
  reg [31:0] debug_writedata;
  reg [31:0] debug_length;
  reg [7:0] debug_spirom_index;//256字节
  reg [0:0] debug_mem_step;
  reg [0:0] debug_spi_step;
  reg [1:0] debug_spi4_step;
  reg [2:0] debug_spi256_step;
  reg [9:0] vga_count;
  reg spirom_debug_read_ack_buff;
  reg spirom_debug_write_ack_buff;
  reg mem_ack_buff;
  reg reset_fifo;
  reg [2:0] debug_address_inc; //1 2 4
  always @(posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      reset_fifo <= 0;
      transfer_req <= 0;
      
      debug_nocache <= 0;
      
      debug_mem_step <= 0;
      debug_spi_step <= 0;
      debug_spi4_step <= 0;
      
      debug_flg <= 0;

      halt_debug<=1;
      debug_step<=0;
      debug_reset_n<=1;

      debug_address_inc <= 0;
      debug_address<=0;
      debug_writedata<=0;
      
      reg_state <= 0;
      debug_regReq <= 0;
      debug_regIsWrite <= 0;
      debug_regAck_buff <= 0;

      command_ack <= 0;
      debug_data_send<=0;
      //debug_data_out<=0;
      
      spirom_debug_read_req<=0;
      spirom_debug_write_req<=0;
      spirom_debug_write_data<=0;
      spirom_debug_cs <= 0;
      spirom_debug_read_ack_buff <= 0;
      spirom_debug_write_ack_buff <= 0;
      
      debug_spirom_index <= 0;
      

      mem_req <= 0;
      mem_ack_buff <= 0;
      mem_cmd <= 0;

      debug_hid <= 0;
      debug_hid_req <= 0;

      cpu_clk_sel <= 0;

      vga_control_by_debugger_reg2 <= 0;
    end else begin
      spirom_debug_read_ack_buff <=  spirom_debug_read_ack;
      spirom_debug_write_ack_buff <= spirom_debug_write_ack;

      debug_regAck_buff <= debug_regAck;

      mem_ack_buff <= mem_ack;
      
      debug_data_send <= 0;

      debug_address_inc <= 0;
      debug_address <= debug_address + debug_address_inc;

      if(command_req && !command_ack)begin
        case(command[7:0])
        
        8'h01 : begin
          debug_data_send<=1; command_ack<=1;
        end //GET_CONST_ECHO

        
        8'h02 : begin debug_data_send<=1; reset_fifo<=0; command_ack<=1; end //HALT_DEBUG
        8'h03 : begin debug_data_send<=1; reset_fifo<=1; command_ack<=1; end //HALT_DEBUG
        8'h04 : begin debug_data_send<=1; transfer_req<=0; command_ack<=1; end //HALT_DEBUG
        8'h05 : begin debug_data_send<=1; transfer_req<=1; command_ack<=1; end //HALT_DEBUG
        

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        8'h10 : begin debug_data_send<=1; halt_debug<=data[0]; command_ack<=1; end //HALT_DEBUG
        8'h11 : begin debug_data_send<=1; cpu_clk_sel <= data[0]; command_ack<=1; end //SET_CPU_CLK
        8'h12 : begin debug_data_send<=1; debug_reset_n<=data[0]; command_ack<=1; end //DEBUG_RESET_N
        8'h13 : begin debug_data_send<=1; debug_nocache <= data[0]; command_ack<=1; end //DEBUG_NO_CACHE
        8'h14 : begin debug_data_send<=1; debug_step<=~debug_step; command_ack<=1; end //DEBUG_STEP
        8'h15 : begin debug_data_send<=1; vga_control_by_debugger_reg2 <= data[0]; command_ack<=1; end//SET_VGA_CONTROL
        8'h16 : begin debug_data_send<=1; debug_address <= data; command_ack<=1; end//SET_DEBUG_ADDRESS
        8'h17 : begin debug_data_send<=1; debug_writedata <= data; command_ack<=1; end//SET_DEBUG_WRITEDATA
        8'h18 : begin debug_data_send<=1; debug_vga_base_addr<= data; command_ack<=1; end // SET_DEBUG_VGA_BASE_ADDR
        8'h19 : begin debug_data_send<=1; debug_flg <= data[0]; command_ack<=1; end //SET_DEBUG_FLG
        8'h1A : begin debug_data_send<=1; debug_hid <= data; command_ack<=1; end //SET_DEBUG_HID
        8'h1B : begin debug_data_send<=1; debug_hid_req <= data[0]; command_ack<=1; end //SET_DEBUG_HID_REQ
        8'h1C : begin debug_data_send<=1; debug_length <= data; command_ack<=1; end //SET_DEBUG_LENGTH

        8'h1D : begin //reg read
          case(reg_state)
          0: begin
            debug_regReq <= 1;
            debug_regIsWrite <= 0;
            reg_state <= 1;
          end
          1: begin
            if(debug_regAck_buff)begin
              debug_regReq <= 0;
              reg_state <= 2;
            end
          end
          2: begin
            if(!debug_regAck_buff)begin
              reg_state <= 3;
            end
          end
          3: begin
            debug_address_inc <= 1;
            debug_data_send<=1;
            reg_state <= 0;
            command_ack <= 1;
          end
          endcase
        end
        8'h1E : begin //reg write
          case(reg_state)
          0: begin
            debug_regReq <= 1;
            debug_regIsWrite <= 1;
            debug_regWriteData <= data;
            reg_state <= 1;
          end
          1: begin
            if(debug_regAck_buff)begin
              debug_regReq <= 0;
              reg_state <= 2;
            end
          end
          2: begin
            if(!debug_regAck_buff)begin
              reg_state <= 3;
            end
          end
          3: begin
            debug_address_inc <= 1;
            reg_state <= 0;
            command_ack <= 1;
          end
          endcase
        end

        8'h1F : begin end

        8'h20,8'h21,8'h22,8'h23,8'h24,8'h25,8'h26,8'h27,
        8'h28,8'h29,8'h2A,8'h2B,8'h2C,8'h2D,8'h2E,8'h2F : begin
          debug_data_send<=1; command_ack<=1;
        end //GET_CONST_ECHO

        8'h30,8'h31,8'h32,8'h33 : begin
          if         (debug_mem_step==0)begin
            debug_mem_step <= 1;
            mem_req <= 1;
            mem_cmd <= command[2:0];
          end else if(debug_mem_step==1)begin
            if(mem_ack_buff)begin
              mem_req <= 0;
              debug_mem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end
        8'h34,8'h35,8'h36,8'h37 : begin
          if         (debug_mem_step==0)begin
            debug_mem_step <= 1;
            mem_req <= 1;
            mem_cmd <= command[2:0];
          end else if(debug_mem_step==1)begin
            debug_mem_step <= 0;
            command_ack <= 1;
          end
        end

`ifdef SPIROM
        8'h70 : begin debug_data_send<=1; spirom_debug_cs <= 1'b0; command_ack<=1; end //SPIROM_DEBUG_CS0
        8'h71 : begin debug_data_send<=1; spirom_debug_cs <= 1'b1; command_ack<=1; end //SPIROM_DEBUG_CS1
        8'h72 : begin //SPIROM_REC
          if         (debug_spi_step==0)begin
            debug_spi_step <= 1;
            spirom_debug_read_req <= 1;
          end else if(debug_spi_step==1)begin
            if(spirom_debug_read_ack_buff)begin
              spirom_debug_read_req <= 0;
              debug_spi_step <= 0;
              debug_data_send<=1; 
              //debug_data_out<=spirom_debug_read_data; 
              command_ack <= 1;
            end
          end
        end
        8'h73 : begin //SPIROM_SND
          if         (debug_spi_step==0)begin
            debug_spi_step <= 1;
            spirom_debug_write_data <= data[7:0];
            spirom_debug_write_req <= 1;
          end else if(debug_spi_step==1)begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_spi_step <= 0;
              debug_data_send<=1; 
              //debug_data_out<=123; 
              command_ack <= 1;
            end
          end
        end
        
        8'h74 : begin //SPIROM_SND4
          case(debug_spi4_step)
          0:begin
            //debug_address is zero
            case(debug_spirom_index[1:0])
            0:spirom_debug_write_data <= data[7:0];
            1:spirom_debug_write_data <= data[15:8];
            2:spirom_debug_write_data <= data[23:16];
            3:spirom_debug_write_data <= data[31:24];
            endcase
            spirom_debug_write_req <= 1;
            debug_spi4_step <= 1;
          end
          1:begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_spirom_index <= debug_spirom_index + 1'b1;
              debug_spi4_step <= 2;
            end
          end
          2:begin
            if(!spirom_debug_write_ack_buff)begin
              debug_spi4_step <= 3;
            end
          end
          3:begin
            if(debug_spirom_index==4)begin
              debug_spirom_index <= 0;
              //debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
            end
            debug_spi4_step <= 0;
          end
          endcase
        end
        
        8'h76 : begin //SPIROM_TRANS_WRITE
          case(debug_spi256_step)
          0:begin
            debug_spirom_index <= 0;
            debug_spi256_step <= 1;
          end
          1:begin
            mem_req <= 1;
            mem_cmd <= 0;//MEM_READ
            debug_spi256_step <= 2;
          end
          2:begin
            if(mem_ack_buff)begin
              mem_req <= 0;
              debug_spi256_step <= 3;
            end
          end
          3:begin
            //debug_address is zero
            case(debug_spirom_index[1:0])
            0:spirom_debug_write_data <= avm_readdata_latch[7:0];
            1:spirom_debug_write_data <= avm_readdata_latch[15:8];
            2:spirom_debug_write_data <= avm_readdata_latch[23:16];
            3:spirom_debug_write_data <= avm_readdata_latch[31:24];
            endcase
            spirom_debug_write_req <= 1;
            debug_spi256_step <= 4;
          end
          4:begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_spirom_index <= debug_spirom_index + 1'b1;
              debug_spi256_step <= 5;
            end
          end
          5:begin
            if(!spirom_debug_write_ack_buff)begin
              debug_spi256_step <= 6;
            end
          end
          6:begin
            if(debug_spirom_index[1:0]==0)begin
              debug_address <= debug_address + 3'b100;
              if(debug_spirom_index==0)begin
                debug_data_send<=1;
                debug_spi256_step <= 0;
                command_ack <= 1;
              end else begin
                debug_spi256_step <= 1;
              end
            end else begin
              debug_spi256_step <= 3;
            end
          end
          endcase
        end
`endif

        default: begin
          command_ack<=1;
        end

        
        endcase

      end

      if(!command_req && command_ack)begin
        command_ack<=0;
      end
      
      if(!debug_tx_to_pc_valid && debug_tx_to_pc_read)begin
        debug_tx_to_pc_read <= 0;
      end
      
      if(debug_rx_from_pc_read && debug_rx_from_pc_valid)begin
        debug_rx_from_pc_valid <= 0;
      end

      if(mem_ack_buff)begin
        mem_req <= 0;
      end

      if(reset_fifo)begin
        debug_mem_step <= 0;
        mem_req <= 0;
      end
    end
  end
//----------------------------------------------------cmd end------------------------------------------------------------------



endmodule
